home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / USection.cp < prev    next >
Encoding:
Text File  |  1991-05-01  |  27.1 KB  |  1,055 lines  |  [TEXT/MPS ]

  1. // USection.cp 
  2. // Copyright © 1984-1991 by Apple Computer Inc. All rights reserved.
  3.  
  4. #ifndef __USECTION__
  5. #include <USection.h>
  6. #endif
  7.  
  8. #ifndef __ULIST__
  9. #include <UList.h>
  10. #endif
  11.  
  12. #ifndef __ALIASES__
  13. #include <Aliases.h>
  14. #endif
  15.  
  16. #ifndef __UFILE__
  17. #include <UFile.h>
  18. #endif
  19.  
  20. #ifndef __USTREAM__
  21. #include <UStream.h>
  22. #endif
  23.  
  24. #ifndef __UDESIGNATOR__
  25. #include <UDesignator.h>
  26. #endif
  27.  
  28. #ifndef __APPLEEVENTS__
  29. #include <AppleEvents.h>
  30. #endif
  31.  
  32. #ifndef __UEVENT__
  33. #include <UEvent.h>
  34. #endif
  35.  
  36. #ifndef __UCOMMAND__
  37. #include <UCommand.h>
  38. #endif
  39.  
  40. #ifndef __UEVTHANDLER__
  41. #include <UEvtHandler.h>
  42. #endif
  43.  
  44. #ifndef __UDOCUMENT__
  45. #include <UDocument.h>
  46. #endif
  47.  
  48. #ifndef __UFILEBASEDDOCUMENT__
  49. #include <UFileBasedDocument.h>
  50. #endif
  51.  
  52. #ifndef __BALLOONS__
  53. #include <Balloons.h>
  54. #endif
  55.  
  56. #ifndef __UVIEW__
  57. #include <UView.h>
  58. #endif
  59.  
  60. #ifndef __UADORNERS__
  61. #include <UAdorners.h>
  62. #endif
  63.  
  64. #ifndef __UEDITIONDOCUMENT__
  65. #include <UEditionDocument.h>
  66. #endif
  67.  
  68. #ifndef __UFILEHANDLER__
  69. #include <UFileHandler.h>
  70. #endif
  71.  
  72. #ifndef __UFAILURE__
  73. #include <UFailure.h>
  74. #endif
  75.  
  76. #ifndef __TEXTEDIT__
  77. #include <TextEdit.h>
  78. #endif
  79.  
  80. #ifndef __UMACAPPUTILITIES__
  81. #include <UMacAppUtilities.h>
  82. #endif
  83.  
  84. #ifndef __UPATCH__
  85. #include <UPatch.h>
  86. #endif
  87.  
  88. #ifndef __UMEMORY__
  89. #include <UMemory.h>
  90. #endif
  91.  
  92. #ifndef __DIALOGS__
  93. #include <Dialogs.h>
  94. #endif
  95.  
  96. #ifndef __UMACAPPGLOBALS__
  97. #include <UMacAppGlobals.h>
  98. #endif
  99.  
  100. #ifndef __RESOURCES__
  101. #include <Resources.h>
  102. #endif
  103.  
  104. #ifndef __ERRORS__
  105. #include <Errors.h>
  106. #endif
  107.  
  108. const short kDirty = TRUE;                        // section IS dirty 
  109. const short kNotDirty = FALSE;                    // section ISN'T dirty 
  110.  
  111. //--------------------------------------------------------------------------------------------------
  112. //******************************************************************************************
  113. //       T S e c t i o n                                                                       
  114. //******************************************************************************************
  115. #pragma segment MASectionRes
  116.  
  117. pascal void TSection::ISection(TEditionDocument* itsDocument,
  118.                                TDesignator* itsDesignator,
  119.                                SectionHandle itsSectionHandle,
  120.                                short itsRsrcID)
  121.  
  122. {
  123.     this->IObject();
  124.  
  125.     fDocument = itsDocument;
  126.     fDesignator = itsDesignator;
  127.     fSectionHandle = itsSectionHandle;
  128.     fRsrcID = itsRsrcID;
  129.     fFound = kFound;
  130.     fCanceled = kDontCancel;
  131.     this->MarkDirty();
  132.     fNewSection = TRUE;                            // yes it is new 
  133. }
  134.  
  135. //--------------------------------------------------------------------------------
  136. #pragma segment MASectionWrite
  137.  
  138. pascal void TSection::Associate(FSSpecPtr newSectionDocument)
  139.  
  140. {
  141.     if (qDebug && !fSectionHandle)
  142.         ProgramBreak("###fSectionHandle is NULL");
  143.  
  144.     FailOSErr(AssociateSection(fSectionHandle, *newSectionDocument));
  145.     this->MarkDirty();
  146. }
  147.  
  148. //--------------------------------------------------------------------------------
  149. #pragma segment MASectionRes
  150.  
  151. pascal void TSection::AttachSectionHandle(SectionHandle itsSectionHandle)
  152.  
  153. {
  154.     if (qDebug && fSectionHandle)
  155.         ProgramBreak("###about to overwrite fSectionHandle");
  156.  
  157.     fSectionHandle = itsSectionHandle;
  158. }
  159.  
  160. //--------------------------------------------------------------------------------
  161. #pragma segment MASectionWrite
  162.  
  163. pascal void TSection::DoNeedDiskSpace(long& ,
  164.                                       long& rsrcForkBytes)
  165.  
  166. {
  167.     if (fSectionHandle)
  168.         rsrcForkBytes += GetHandleSize((Handle)fSectionHandle) + GetHandleSize((Handle)(*fSectionHandle)->alias) + fDesignator->GetSpecificationSize() + sizeof(IDType);
  169. }
  170.  
  171. //--------------------------------------------------------------------------------
  172. #pragma segment MASectionClose
  173.  
  174. pascal void TSection::Free(void)
  175.  
  176. {
  177.     fDocument->RemoveSection(this);
  178.  
  179.     this->UnRegister();
  180.     fDesignator = (TDesignator *)FreeIfObject(fDesignator);
  181.     fSectionHandle = DisposeIfSectionHandle(fSectionHandle);
  182.     inherited::Free();
  183. }
  184.  
  185. //--------------------------------------------------------------------------------
  186. #pragma segment MASectionRes
  187.  
  188. pascal void TSection::GetEditionName(Str255& name)
  189.  
  190. {
  191.     this->UpdateEditionInfo();
  192.     name = fLastEditionInfo.container.theFile.name;
  193. }
  194.  
  195. //--------------------------------------------------------------------------------
  196. #pragma segment MASectionRes
  197.  
  198. pascal TFileHandler* TSection::GetFileHandler(void)
  199.  
  200. {
  201.     if (fDocument)
  202.         return fDocument->GetFileHandler();
  203.     else
  204.         return NULL;
  205. }
  206.  
  207. //--------------------------------------------------------------------------------
  208. #pragma segment MASectionRes
  209.  
  210. pascal SectionType TSection::GetSectionType(void)
  211.  
  212. {
  213.     if (fSectionHandle)
  214.         return (*fSectionHandle)->kind;
  215.     else
  216.         return (SectionType) - 1;
  217. }
  218.  
  219. //--------------------------------------------------------------------------------
  220. #pragma segment MASectionRes
  221.  
  222. pascal UpdateMode TSection::GetUpdateMode(void)
  223.  
  224. {
  225.     if (fSectionHandle)
  226.         return (*fSectionHandle)->mode;
  227.     else
  228.         return (UpdateMode) - 1;
  229. }
  230.  
  231. //--------------------------------------------------------------------------------
  232. #pragma segment MASectionRead
  233.  
  234. pascal void TSection::DoRead(TFile* aFile)
  235.  
  236. {
  237.     if (!aFile->IsRsrcForkOpen())
  238.     {
  239.         if (qDebug)
  240.             ProgramBreak("###resource fork isn''t open");
  241.     }
  242.     else
  243.     {
  244.         FailInfo fi;
  245.  
  246.         // set up for failure handler 
  247.         TResourceStream * aResourceStream = NULL;
  248.         short oldResFile;
  249.         
  250.         VOLATILE(aResourceStream);
  251.         VOLATILE(oldResFile);
  252.         
  253.         fSectionHandle = NULL;
  254.         fDesignator = NULL;
  255.  
  256.         if (fi.Try())
  257.         {
  258.             Handle aHandle;
  259.             IDType designatorID;
  260.  
  261.             oldResFile = aFile->UseResource();    // set the current ResFile
  262.  
  263.             // read in the section handle from a rSectionType resource 
  264.             aHandle = Get1Resource(rSectionType, fRsrcID);
  265.             FailResError();
  266.             DetachResource(aHandle);
  267.             FailResError();
  268.             fSectionHandle = (SectionHandle)aHandle;
  269.             (*fSectionHandle)->alias = NULL;    // so failure handler works
  270.  
  271.             // read in the alias handle from a rAliasType resource 
  272.             aHandle = Get1Resource(rAliasType, fRsrcID);
  273.             FailResError();
  274.             DetachResource(aHandle);
  275.             FailResError();
  276.             (*fSectionHandle)->alias = (AliasHandle)aHandle;
  277.  
  278.             // read in the associated designator 
  279.             aResourceStream = new TResourceStream;
  280.             aResourceStream->IResourceStream(kDesignatorResType, fRsrcID);
  281.  
  282.             aResourceStream->ReadLong(*((long*)&designatorID));    // read in the signature
  283.             fDesignator = (TDesignator *)NewStdObject(designatorID);
  284.             fDesignator->InitFromStream(fDocument, aResourceStream);
  285.  
  286.             aResourceStream->Free();
  287.  
  288.             UseResFile(oldResFile);                // restore the current ResFile
  289.  
  290.             fi.Success();
  291.         }
  292.         else    // Recover
  293.         {
  294.             // free any memory that was allocated
  295.             aResourceStream = (TResourceStream *)FreeIfObject(aResourceStream);
  296.             fSectionHandle = DisposeIfSectionHandle(fSectionHandle);
  297.             fDesignator = (TDesignator*) FreeIfObject(fDesignator);
  298.  
  299.             UseResFile(oldResFile);                // restore the current ResFile
  300.  
  301.             fi.ReSignal();                        // Optional. Omit to continue.
  302.         }
  303.  
  304.         // register the section 
  305.         fFound = kFound;                        // let's assume that it's found 
  306.         fNewSection = FALSE;                    // no it is not new 
  307.         OSErr err = this->Register();
  308.         if (err == containerNotFoundWrn)
  309.             fFound = kNotFound;
  310.         else if (err != noErr)
  311.             FailOSErr(err);
  312.     }
  313. }
  314.  
  315. //--------------------------------------------------------------------------------
  316. #pragma segment MASectionWrite
  317.  
  318. pascal void TSection::DoWrite(TFile* aFile,
  319.                               Boolean)
  320.  
  321. {
  322.     FSSpec itsFile;
  323.     Str255 rsrcName;
  324.     Handle aHandle;
  325.     EditionInfoRecord editionInfo;
  326.     IDType designatorID;
  327.  
  328.     if (!fSectionHandle)
  329.     {
  330.         if (qDebug)
  331.             ProgramBreak("###SectionHandle is NULL");
  332.     }
  333.     else
  334.     {
  335.         if (!aFile->IsRsrcForkOpen())
  336.         {
  337.             if (qDebug)
  338.                 ProgramBreak("###resource fork isn't open");
  339.         }
  340.         else
  341.         {
  342.             FailInfo fi;
  343.             TResourceStream * aResourceStream = NULL;
  344.             short oldResFile;
  345.  
  346.             VOLATILE(aResourceStream);
  347.             VOLATILE(oldResFile);
  348.  
  349.             if (fi.Try())
  350.             {
  351.                 oldResFile = aFile->UseResource();    // set the current ResFile
  352.     
  353.                 // ensure that the section object knows that it belongs to the file 
  354.                 aFile->GetFileSpec(itsFile);
  355.                 this->Associate(&itsFile);
  356.     
  357.                 // prepare to write out our section resources 
  358.                 FailOSErr(GetEditionInfo(fSectionHandle, editionInfo));
  359.                 rsrcName = editionInfo.container.theFile.name;
  360.     
  361.                 // add the alias handle as an rAliasType resource 
  362.                 aHandle = (Handle)(*fSectionHandle)->alias;
  363.                 FailOSErr(HandToHand(aHandle));
  364.                 AddResource(aHandle, rAliasType, fRsrcID, rsrcName);
  365.                 FailResError();
  366.     
  367.                 // add the section handle as an rSectionType resource 
  368.                 aHandle = (Handle)fSectionHandle;
  369.                 FailOSErr(HandToHand(aHandle));
  370.                 AddResource(aHandle, rSectionType, fRsrcID, rsrcName);
  371.                 FailResError();
  372.     
  373.                 // ask the designator to write its specification to a TResourceStream 
  374.                 aHandle = NewPermHandle(2);
  375.                 AddResource(aHandle, kDesignatorResType, fRsrcID, rsrcName);
  376.                 FailResError();
  377.                 WriteResource(aHandle);
  378.                 ReleaseResource(aHandle);
  379.     
  380.                 // write the designator to a resource stream
  381.                 aResourceStream = new TResourceStream;
  382.                 aResourceStream->IResourceStream(kDesignatorResType, fRsrcID);
  383.     
  384.                 // ??? replace the next 3 lines  with aResourceStream->WriteStreamObject(fDesignator)
  385.                 designatorID = fDesignator->GetSignature();
  386.                 aResourceStream->WriteLong(designatorID);    // write its signature 
  387.                 fDesignator->WriteToStream(aResourceStream);// write its specification 
  388.     
  389.                 aResourceStream->Free();
  390.     
  391.                 UseResFile(oldResFile);                // restore the current ResFile
  392.     
  393.                 fDirty = kNotDirty;                    // it's been saved, it's not dirty 
  394.                 fNewSection = FALSE;                // no it is not new 
  395.                 fi.Success();
  396.             }
  397.             else    // Recover
  398.             {
  399.                 aResourceStream = (TResourceStream *)FreeIfObject(aResourceStream);
  400.  
  401.                 UseResFile(oldResFile);                // restore the current ResFile
  402.                 fi.ReSignal();                        // Optional. Omit to continue.
  403.             }
  404.     
  405.         }
  406.     }
  407. }
  408.  
  409. //--------------------------------------------------------------------------------
  410. #pragma segment MASectionWrite
  411.  
  412. pascal void TSection::Delete(void)
  413.  
  414. {
  415.     // NOTE: may only need to do this if the file handler's fHowToSave is save-in-place!!!
  416.     Handle h;
  417.  
  418.     // remove the alias handle from the resource fork 
  419.     h = Get1Resource(rAliasType, fRsrcID);
  420.     if (h)
  421.     {
  422.         RmveResource(h);
  423.         FailResError();
  424.         h = DisposeIfHandle(h);
  425.     }
  426.  
  427.     // remove the section handle from the resource fork 
  428.     h = Get1Resource(rSectionType, fRsrcID);
  429.     if (h)
  430.     {
  431.         RmveResource(h);
  432.         FailResError();
  433.         h = DisposeIfHandle(h);
  434.     }
  435.  
  436.     // remove the designator handle from the resource fork 
  437.     h = Get1Resource(kDesignatorResType, fRsrcID);
  438.     if (h)
  439.     {
  440.         RmveResource(h);
  441.         FailResError();
  442.         h = DisposeIfHandle(h);
  443.     }
  444. }
  445.  
  446. //--------------------------------------------------------------------------------
  447. #pragma segment MASectionRes
  448.  
  449. pascal Boolean TSection::IsRegistered(void)
  450.  
  451. {
  452.     // it's registered if the Edition Manager thinks it's registered 
  453.     if (fSectionHandle)
  454.         return IsRegisteredSection(fSectionHandle) == noErr;
  455.     else
  456.         return FALSE;
  457. }
  458.  
  459. //--------------------------------------------------------------------------------
  460. #pragma segment MASectionRes
  461.  
  462. pascal Boolean TSection::IsSectionSelected(void)
  463.  
  464. {
  465.     if (fDocument)
  466.         return fDocument->IsSectionSelected(this);
  467.     else
  468.         return FALSE;
  469. }
  470.  
  471. //--------------------------------------------------------------------------------
  472. #pragma segment MASectionRes
  473.  
  474. pascal void TSection::MarkDirty(void)
  475.  
  476. {
  477.     fDirty = kDirty;
  478. }
  479.  
  480. //--------------------------------------------------------------------------------
  481. #pragma segment MASectionRes
  482.  
  483. pascal Boolean TSection::IsDirty(void)
  484.  
  485. {
  486.     return fDirty;
  487. }
  488.  
  489. //--------------------------------------------------------------------------------
  490. #pragma segment MASectionRes
  491.  
  492. pascal OSErr TSection::Register(void)
  493.  
  494. {
  495.     OSErr err = noErr;
  496.  
  497.     if (!this->IsRegistered())
  498.     {
  499.         TFileHandler * aFileHandler = this->GetFileHandler();
  500.         if (aFileHandler && aFileHandler->FileExists())
  501.         {
  502.             if (aFileHandler->fFile)
  503.             {
  504.                 FSSpec theFileSpec;
  505.                 
  506.                 Boolean aliasWasUpdated;
  507.                 aFileHandler->fFile->GetFileSpec(theFileSpec);
  508.                 err = RegisterSection(theFileSpec, fSectionHandle, aliasWasUpdated);
  509.  
  510.                 // if (aliasWasUpdated, mark section as dirty so that user saves changed edition 
  511.                 if (aliasWasUpdated)
  512.                     this->MarkDirty();
  513.  
  514.                 // if (RegisterSection was successful, update edition info 
  515.                 if (err == noErr)
  516.                     this->UpdateEditionInfo();
  517.             }
  518.             else
  519.             {
  520.                 err = fnfErr;
  521.                 if (qDebug)
  522.                     ProgramBreak("how to call RegisterSection if there isn't a FileSpec???");
  523.             }
  524.         }
  525.         else
  526.         {
  527.             err = fnfErr;
  528.             if (qDebug)
  529.                 ProgramBreak("how to call RegisterSection if there isn't a TFile???");
  530.         }
  531.     }
  532.     return err;
  533. }
  534.  
  535. //--------------------------------------------------------------------------------
  536. #pragma segment MASectionRes
  537.  
  538. pascal void TSection::UnRegister(void)
  539.  
  540. {
  541.     if (this->IsRegistered())
  542.         FailOSErr(UnRegisterSection(fSectionHandle));
  543. }
  544.  
  545. //--------------------------------------------------------------------------------
  546. #pragma segment MASectionRes
  547.  
  548. pascal void TSection::UpdateEditionInfo(void)
  549.  
  550. {
  551.     EditionInfoRecord editionInfo;
  552.  
  553.     if (this->IsRegistered() && (GetEditionInfo(fSectionHandle, editionInfo) == noErr))
  554.         fLastEditionInfo = editionInfo;
  555. }
  556.  
  557. //--------------------------------------------------------------------------------
  558. #pragma segment MASectionRes
  559.  
  560. pascal void TSection::CancelSection(Boolean cancel)
  561.  
  562. {
  563.     OSErr err;
  564.  
  565.     if (cancel != fCanceled)
  566.         if (cancel == kCancel)
  567.         {
  568.             this->UnRegister();
  569.             fCanceled = kCancel;                // it IS canceled 
  570.         }
  571.         else
  572.         {
  573.             err = this->Register();
  574.             if ((err != noErr) && (err != containerNotFoundWrn) && (err != notThePublisherWrn) && (err != multiplePublisherWrn))
  575.                 FailOSErr(err);
  576.             fCanceled = kDontCancel;            // it IS !canceled 
  577.         }
  578. }
  579.  
  580. //--------------------------------------------------------------------------------------------------
  581. #pragma segment MAFields
  582.  
  583. pascal void TSection::Fields(TObject* obj)        // override 
  584.  
  585. {
  586.     long aLongint;
  587.     Boolean isARegisteredSection;
  588.  
  589.     obj->DoToField("TSection", NULL, bClass);
  590.     obj->DoToField("fDocument", &fDocument, bObject);
  591.     obj->DoToField("fDesignator", &fDesignator, bObject);
  592.     aLongint = (long)fSectionHandle;
  593.     obj->DoToField("fSectionHandle", &aLongint, bLongInt);
  594.     if (fSectionHandle)
  595.     {
  596.         SectionRecord aSectionRecord = **fSectionHandle;
  597.         obj->DoToField("**fSectionHandle", &aSectionRecord, bSectionRecord);
  598.     }
  599.     obj->DoToField("fRsrcID", (Ptr) & fRsrcID, bInteger);
  600.     obj->DoToField("fFound", (Ptr) & fFound, bBoolean);
  601.     obj->DoToField("fCanceled", (Ptr) & fCanceled, bBoolean);
  602.     obj->DoToField("fDirty", (Ptr) & fDirty, bBoolean);
  603.  
  604.     isARegisteredSection = this->IsRegistered();
  605.     obj->DoToField("isARegisteredSection", &isARegisteredSection, bBoolean);
  606.  
  607.     inherited::Fields(obj);
  608. }
  609.  
  610. //******************************************************************************************
  611. //       T P u b l i s h e r                                                                   
  612. //******************************************************************************************
  613. #pragma segment MASectionRes
  614.  
  615. pascal void TPublisher::IPublisher(TEditionDocument* itsDocument,
  616.                                    TDesignator* itsDesignator,
  617.                                    SectionHandle itsSectionHandle,
  618.                                    short itsRsrcID)
  619.  
  620. {
  621.     this->ISection(itsDocument, itsDesignator, itsSectionHandle, itsRsrcID);
  622. }
  623.  
  624. //--------------------------------------------------------------------------------
  625. #pragma segment MASectionRes
  626.  
  627. pascal void TPublisher::DoUpdate(ChangeID& theChange,
  628.                                  TObject* changedObject,
  629.                                  TObject* changedBy)// override 
  630.  
  631. {
  632.     unsigned long secs;
  633.  
  634.     // mark this publisher as changed 
  635.     GetDateTime(secs);
  636.     this->MarkAsChanged(secs);
  637.  
  638.     inherited::DoUpdate(theChange, changedObject, changedBy);
  639. }
  640.  
  641. //--------------------------------------------------------------------------------
  642. #pragma segment MASectionWrite
  643.  
  644. pascal void TPublisher::Publish(void)
  645.  
  646. {
  647.     EditionRefNum refNum;
  648.     FSSpec aFSSpec;
  649.     FSSpecPtr aFSSpecPtr = NULL;
  650.     FailInfo fi;
  651.     OSErr err;
  652.     TSectionStream* aSectionStream;
  653.  
  654.     VOLATILE(refNum);
  655.  
  656.     // open the edition file 
  657.     TFileHandler* aFileHandler = this->GetFileHandler();
  658.     if (aFileHandler && aFileHandler->FileExists())
  659.     {
  660.         aFileHandler->fFile->GetFileSpec(aFSSpec);
  661.         aFSSpecPtr = &aFSSpec;
  662.     }
  663.     // ??? It's dangerous to dereference aFSSpecPtr on the next line when it could be NULL,
  664.     // however, the declaration of OpenNewEdition() requires an FSSpec&.
  665.     err = OpenNewEdition(fSectionHandle, aFileHandler->fFile->fCreator, *aFSSpecPtr, refNum);
  666.     if (err == noErr)                            /* DON'T signal failure if the OpenNewEdition
  667.                                                   fails, just continue without publishing */
  668.     {
  669.         if (fi.Try())
  670.         {
  671.             // Create a section stream to write the published data to.
  672.             aSectionStream = new TSectionStream;
  673.             aSectionStream->ISectionStream(refNum, '    ');
  674.  
  675.             /* The order in which the application publishes to the edition container file indicates
  676.               to the client application the preferred order for subscribers! So, publish the TEXT
  677.               or PICT or 'snd ' (at least one is required) in the order prefered.
  678.               N.B.: The Edition Manager will set the edition container file's file type
  679.               according to which type was published first: 'edtp' if PICT was published first,
  680.               'edtt' if TEXT was published first, and 'edts' if 'snd ' was published first. */
  681.             if (fDocument->GetPublishPreference() == 'PICT')
  682.             {
  683.                 aSectionStream->Reset('PICT', 0);
  684.                 fDocument->DoWriteData('PICT', fDesignator, aSectionStream);
  685.                 aSectionStream->Reset('TEXT', 0);
  686.                 fDocument->DoWriteData('TEXT', fDesignator, aSectionStream);
  687.                 aSectionStream->Reset('snd ', 0);
  688.                 fDocument->DoWriteData('snd ', fDesignator, aSectionStream);
  689.             }
  690.             else if (fDocument->GetPublishPreference() == 'TEXT')
  691.             {
  692.                 aSectionStream->Reset('TEXT', 0);
  693.                 fDocument->DoWriteData('TEXT', fDesignator, aSectionStream);
  694.                 aSectionStream->Reset('PICT', 0);
  695.                 fDocument->DoWriteData('PICT', fDesignator, aSectionStream);
  696.                 aSectionStream->Reset('snd ', 0);
  697.                 fDocument->DoWriteData('snd ', fDesignator, aSectionStream);
  698.             }
  699.             else if (fDocument->GetPublishPreference() == 'snd ')
  700.             {
  701.                 aSectionStream->Reset('snd ', 0);
  702.                 fDocument->DoWriteData('snd ', fDesignator, aSectionStream);
  703.                 aSectionStream->Reset('TEXT', 0);
  704.                 fDocument->DoWriteData('TEXT', fDesignator, aSectionStream);
  705.                 aSectionStream->Reset('PICT', 0);
  706.                 fDocument->DoWriteData('PICT', fDesignator, aSectionStream);
  707.             }
  708.  
  709.             // last priority: publish the application's custom data (this is optional) 
  710.             aSectionStream->Reset(fDocument->fScrapType, 0);
  711.             fDocument->DoWriteData(fDocument->fScrapType, fDesignator, aSectionStream);
  712.  
  713.             // Free the stream
  714.             aSectionStream->Free();
  715.  
  716.             fi.Success();
  717.         }
  718.         else    // Recover
  719.         {
  720.             // Free the stream
  721.             aSectionStream->Free();
  722.  
  723.             // If there is a failure during publishing close the edition file without saving
  724.             // the changes (pass FALSE for successful). This ensures that the publisher will
  725.             // get a shot at publishing again later.
  726.             err = CloseEdition(refNum, FALSE);
  727.  
  728.             fi.ReSignal();                        // Optional. Omit to continue.
  729.         }
  730.         // close the edition file, passing TRUE for the successful parameter 
  731.         FailOSErr(CloseEdition(refNum, TRUE));
  732.     }
  733. }
  734.  
  735. //--------------------------------------------------------------------------------
  736. #pragma segment MASectionWrite
  737.  
  738. pascal void TPublisher::DoWrite(TFile* aFile,
  739.                                 Boolean makingCopy)// override 
  740.  
  741. {
  742.     inherited::DoWrite(aFile, makingCopy);
  743.  
  744.     if ((!fDocument->fStopAllEditions) && fSectionHandle && (this->GetUpdateMode() == pumOnSave) && this->IsChanged())
  745.         this->Publish();
  746. }
  747.  
  748. //--------------------------------------------------------------------------------
  749. #pragma segment MASectionWrite
  750.  
  751. pascal void TPublisher::Delete(void)            // override 
  752.  
  753. {
  754.     this->DeleteEditionFile();
  755.  
  756.     inherited::Delete();
  757. }
  758.  
  759. //--------------------------------------------------------------------------------
  760. #pragma segment MASectionWrite
  761.  
  762. pascal void TPublisher::DeleteEditionFile(void)
  763.  
  764. {
  765.     FSSpec theFile;
  766.  
  767.     // get the edition container file's FSSpec - from updated fLastEditionInfo 
  768.     if (this->IsRegistered())
  769.         this->UpdateEditionInfo();
  770.     theFile = fLastEditionInfo.container.theFile;
  771.  
  772.     // cancel the section - this unregisters the section 
  773.     this->CancelSection(kCancel);
  774.  
  775.     // delete the edition container file 
  776.     FailOSErr(DeleteEditionContainerFile(theFile));
  777. }
  778.  
  779. //--------------------------------------------------------------------------------
  780. #pragma segment MASectionRes
  781.  
  782. pascal Boolean TPublisher::IsChanged(void)
  783.  
  784. {
  785.     EditionInfoRecord editionInfo;
  786.  
  787.  
  788.     if (fSectionHandle)
  789.     {
  790.         FailOSErr(GetEditionInfo(fSectionHandle, editionInfo));
  791.         return editionInfo.mdDate != (*fSectionHandle)->mdDate;
  792.     }
  793.     else
  794.         return FALSE;
  795. }
  796.  
  797. //--------------------------------------------------------------------------------
  798. #pragma segment MASectionRes
  799.  
  800. pascal void TPublisher::MarkAsChanged(TimeStamp mdDate)
  801.  
  802. {
  803.     if (fSectionHandle)
  804.         (*fSectionHandle)->mdDate = mdDate;
  805. }
  806.  
  807. //--------------------------------------------------------------------------------------------------
  808. #pragma segment MAFields
  809.  
  810. pascal void TPublisher::Fields(TObject* obj)    // override 
  811.  
  812. {
  813.     obj->DoToField("TPublisher", (Ptr)NULL, bClass);
  814.  
  815.     inherited::Fields(obj);
  816. }
  817.  
  818. //******************************************************************************************
  819. //       T S u b s c r i b e r                                                               
  820. //******************************************************************************************
  821. #pragma segment MASectionRes
  822.  
  823. pascal void TSubscriber::ISubscriber(TEditionDocument* itsDocument,
  824.                                      TDesignator* itsDesignator,
  825.                                      SectionHandle itsSectionHandle,
  826.                                      short itsRsrcID)
  827.  
  828. {
  829.     this->ISection(itsDocument, itsDesignator, itsSectionHandle, itsRsrcID);
  830.  
  831.     // ensure that the document is notified of any and all changes to the subscriber 
  832.     this->AddDependent(itsDocument);
  833. }
  834.  
  835. //--------------------------------------------------------------------------------
  836. #pragma segment MASectionRead
  837.  
  838. pascal void TSubscriber::SubscribeIfNewer(void)
  839.  
  840. {
  841.     if ((!fDocument->fStopAllEditions) && fSectionHandle && (this->GetUpdateMode() == sumAutomatic) && this->IsNewerEditionAvailable())
  842.         this->Subscribe();
  843. }
  844.  
  845. //--------------------------------------------------------------------------------
  846. #pragma segment MASectionRead
  847.  
  848. pascal void TSubscriber::Subscribe(void)
  849.  
  850. {
  851.     EditionRefNum refNum;
  852.     FailInfo fi;
  853.     Size formatSize;
  854.     OSErr err;
  855.     TSectionStream* aSectionStream;
  856.  
  857.     VOLATILE(refNum);
  858.  
  859.     FailOSErr(OpenEdition(fSectionHandle, refNum));
  860.  
  861.     if (fi.Try())
  862.     {
  863.         // Create a section stream to read the published data from.
  864.         aSectionStream = new TSectionStream;
  865.         aSectionStream->ISectionStream(refNum, '    ');
  866.         
  867.         // Top priority: subscribe to private types.
  868.         err = EditionHasFormat(refNum, fDocument->fScrapType, formatSize);
  869.         if ((err == noErr) && (formatSize > 0))
  870.         {
  871.             aSectionStream->Reset(fDocument->fScrapType, formatSize);
  872.             fDocument->DoReadData(fDocument->fScrapType, fDesignator, aSectionStream, formatSize);
  873.         }
  874.         else
  875.         {
  876.             // subscribe to one or more of the required data types 
  877.             err = EditionHasFormat(refNum, 'PICT', formatSize);
  878.             if ((err == noErr) && (formatSize > 0))
  879.             {
  880.                 aSectionStream->Reset('PICT', formatSize);
  881.                 fDocument->DoReadData('PICT', fDesignator, aSectionStream, formatSize);
  882.             }
  883.             err = EditionHasFormat(refNum, 'TEXT', formatSize);
  884.             if ((err == noErr) && (formatSize > 0))
  885.             {
  886.                 aSectionStream->Reset('TEXT', formatSize);
  887.                 fDocument->DoReadData('TEXT', fDesignator, aSectionStream, formatSize);
  888.             }
  889.             err = EditionHasFormat(refNum, 'snd ', formatSize);
  890.             if ((err == noErr) && (formatSize > 0))
  891.             {
  892.                 aSectionStream->Reset('snd ', formatSize);
  893.                 fDocument->DoReadData('snd ', fDesignator, aSectionStream, formatSize);
  894.             }
  895.         }
  896.  
  897.         // Free the stream
  898.         aSectionStream->Free();
  899.  
  900.         fi.Success();
  901.     }
  902.     else    // Recover
  903.     {
  904.         // Free the stream
  905.         aSectionStream->Free();
  906.  
  907.         // If there is a failure during subscribing, close the edition file without saving
  908.         // the changes (pass FALSE for successful). This ensures that the subscriber will
  909.         // get a shot at subscribing again later.
  910.         err = CloseEdition(refNum, FALSE);
  911.  
  912.         fi.ReSignal();                            // Optional. Omit to continue.
  913.     }
  914.  
  915.     // close the edition file 
  916.     FailOSErr(CloseEdition(refNum, TRUE));
  917.  
  918.     this->Changed(cSubscriberChanged, this);    // notify dependents 
  919. }
  920.  
  921. //--------------------------------------------------------------------------------
  922. #pragma segment MASectionRes
  923.  
  924. pascal Boolean TSubscriber::IsNewerEditionAvailable(void)
  925.  
  926. {
  927.     EditionInfoRecord editionInfo;
  928.  
  929.     if (fSectionHandle)
  930.     {
  931.         FailOSErr(GetEditionInfo(fSectionHandle, editionInfo));
  932.         return (editionInfo.mdDate != (*fSectionHandle)->mdDate);
  933.     }
  934.     else
  935.         return FALSE;
  936. }
  937.  
  938. //--------------------------------------------------------------------------------
  939. #pragma segment MASectionRes
  940.  
  941. pascal void TSubscriber::OpenPublisher(void)
  942.  
  943. {
  944.     EditionInfoRecord editionInfo;
  945.  
  946.     FailOSErr(GetEditionInfo(fSectionHandle, editionInfo));
  947.     FailOSErr(GoToPublisherSection(editionInfo.container));
  948. }
  949.  
  950. //--------------------------------------------------------------------------------------------------
  951. #pragma segment MAFields
  952.  
  953. pascal void TSubscriber::Fields(TObject* obj)    // override 
  954.  
  955. {
  956.     obj->DoToField("TSubscriber", (Ptr)NULL, bClass);
  957.  
  958.     inherited::Fields(obj);
  959. }
  960.  
  961. //--------------------------------------------------------------------------------------------------
  962. #pragma segment MAStreamCreate
  963.  
  964. pascal void TSectionStream::Initialize(void)        // override 
  965. {
  966.     inherited::Initialize();
  967.  
  968.     fEditionRefNum = 0;
  969.     fEditionOSType = '    ';
  970.     fPosition = 0;
  971.     fSize = 0;
  972. }
  973.  
  974. //--------------------------------------------------------------------------------
  975. #pragma segment MAStreamCreate
  976.  
  977. pascal void TSectionStream::ISectionStream(EditionRefNum itsEditionRefNum, OSType itsEditionOSType)
  978. {
  979.     this->IStream();
  980.  
  981.     fEditionRefNum = itsEditionRefNum;
  982.     fEditionOSType = itsEditionOSType;
  983. }
  984.  
  985. //--------------------------------------------------------------------------------
  986. #pragma segment MASectionWrite
  987.  
  988. pascal void TSectionStream::Reset(OSType itsEditionOSType, long itsSize)
  989. {
  990.     this->SetPosition(0);
  991.     fEditionOSType = itsEditionOSType;
  992.     fSize = itsSize;
  993. }
  994.  
  995. //--------------------------------------------------------------------------------------------------
  996. #pragma segment MAStreamUtil
  997.  
  998. pascal long TSectionStream::GetPosition(void)    // override 
  999. {
  1000.     return fPosition;
  1001. }
  1002.  
  1003. //--------------------------------------------------------------------------------------------------
  1004. #pragma segment MAStreamUtil
  1005.  
  1006. pascal void TSectionStream::SetPosition(long newPosition)// override 
  1007. {
  1008.     fPosition = newPosition;
  1009.  
  1010.     if (fPosition > fSize)                        // Adjust the size if necessary. 
  1011.         fSize = fPosition;
  1012. }
  1013.  
  1014. //--------------------------------------------------------------------------------------------------
  1015. #pragma segment MAStreamUtil
  1016.  
  1017. pascal long TSectionStream::GetSize(void)
  1018. {
  1019.     return fSize;
  1020. }
  1021.  
  1022. //--------------------------------------------------------------------------------------------------
  1023. #pragma segment MAStreamUtil
  1024.  
  1025. pascal void TSectionStream::SetSize(long newSize)// override 
  1026. {
  1027.     fSize = newSize;
  1028.  
  1029.     if (newSize < fPosition)                    // If we shrunk the size, then we have to adjust the position.
  1030.         fPosition = newSize;
  1031. }
  1032.  
  1033. //--------------------------------------------------------------------------------
  1034. #pragma segment MASectionWrite
  1035.  
  1036. pascal void TSectionStream::WriteBytes(const void* p, long count)
  1037. {
  1038.     FailOSErr(SetEditionFormatMark(fEditionRefNum, fEditionOSType, this->GetPosition()));
  1039.     FailOSErr(WriteEdition(fEditionRefNum, fEditionOSType, p, count));
  1040.  
  1041.     this->SetPosition(fPosition + count);        // Advance the position. 
  1042. }
  1043.  
  1044. //--------------------------------------------------------------------------------------------------
  1045. #pragma segment MAStreamRead
  1046.  
  1047. pascal void TSectionStream::ReadBytes(void* p, long count)    // override 
  1048. {
  1049.     FailOSErr(SetEditionFormatMark(fEditionRefNum, fEditionOSType, this->GetPosition()));
  1050.     FailOSErr(ReadEdition(fEditionRefNum, fEditionOSType, p, count));
  1051.  
  1052.     this->SetPosition(fPosition + count);        // Advance the position. 
  1053. }
  1054.  
  1055.